Function.RegisterNamespace("Test");

[Import("../../Source/Extensions.js/Object.js")]
[Fixture,this]
Test.Object=function(){
    [Fixture]
    function Clone(){
        [Fact]
        function ThrowsIfNotPassedInstance(){
            var expected="Object.Clone: no argument passed for 'instance'.";
            
            var actual=Record.Exception(function(){
                Object.Clone();
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ReturnsNullIfTargetIsNull(){
            var actual=Object.Clone(null);
        
            Assert.Null(actual);
        }

        [Fact]
        function ReturnsUndefinedIfTargetIsUndefined(){
            var actual=Object.Clone(undefined);
        
            Assert.Undefined(actual);
        }
        
        [Fact]
        function ReturnsNewArrayIfPassed(){
            var expected=[1,2,3];
            
            var actual=Object.Clone(expected);
            
            Assert.NotSame(expected,actual);
        }
        
        [Fact]
        function ReturnsCopyOfArrayPassed(){
            var expected=[1,2,3];
            
            var actual=Object.Clone(expected);
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function CopiesExpandoPropertyOntoNewArray(){
            var expected="expected";
            var target=[];
            target[expected]=expected;
            
            var actual=Object.Clone(target)[expected];
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ReturnsBooleanIfPassedBoolean(){
            var expected=true;
            
            var actual=Object.Clone(expected);
            
            Assert.True(Object.IsType(Boolean,actual));
        }

        [Fact]
        function ReturnsValueOfBooleanIfPassedBoolean(){
            var expected=true;
            
            var actual=Object.Clone(expected);
            
            Assert.True(Boolean.Equals(expected,actual));
        }

        [Fact]
        function CopiesExpandoPropertyOntoNewBoolean(){
            var expected="expected";
            var target=new Boolean();
            target[expected]=expected;
         
            var actual=Object.Clone(target)[expected];
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ReturnsErrorIfPassedError(){
            var expected=new Error("expected");

            var actual=Object.Clone(expected);
            
            Assert.True(Object.IsType(Error,actual));
        }
        
        [Fact]
        function ReturnsNewErrorIfPassedError(){
            var expected=new Error("expected");
        
            var actual=Object.Clone(expected);
            
            Assert.NotSame(expected,actual);
        }

        [Fact]
        function ReturnsValueOfErrorIfPassedError(){
            var expected=new Error("expected");
        
            var actual=Object.Clone(expected);
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function CopiesExpandoPropertyOntoNewError(){
            var expected="expected";
            var target=new Error();
            target[expected]=expected;
            
            var actual=Object.Clone(target)[expected];

            Assert.Equal(expected,actual);
        }

        [Fact]
        function ReturnsFunctionIfPassedFunction(){
            var expected=new Function("var expected='expected';");

            var actual=Object.Clone(expected);
            
            Assert.True(Object.IsType(Function,actual));
        }
        
        [Fact]
        function ReturnsSameFunctionIfPassedFunction(){
            var expected=new Function("var expected='expected';");

            var actual=Object.Clone(expected);

            Assert.Same(expected,actual);
        }

        [Fact]
        function ReturnsNumberIfPassedNumber(){
            var expected=5;
            
            var actual=Object.Clone(expected);
            
            Assert.True(Object.IsType(Number,actual));
        }

        [Fact]
        function ReturnsValueOfNumberIfPassedNumber(){
            var expected=5;
            
            var actual=Object.Clone(expected);
            
            Assert.True(Number.Equals(expected,actual));
        }
        
        [Fact]
        function CopiesExpandoPropertyOntoNewNumber(){
            var expected="expected";
            var target=new Number();
            target[expected]=expected;
            
            var actual=Object.Clone(target)[expected];
            
            Assert.Equal(expected,actual);
        }
                
        [Fact]
        function ReturnsStringIfPassedString(){
            var expected="expected";
            
            var actual=Object.Clone(expected);
            
            Assert.True(Object.IsType(String,actual));
        }

        [Fact]
        function ReturnsValueOfStringIfPassedString(){
            var expected="expected";
            
            var actual=Object.Clone(expected);
            
            Assert.True(String.Equals(expected,actual));
        }
        
        [Fact]
        function CopiesExpandoPropertyOntoNewString(){
            var expected="expected";
            var target=new String();
            target[expected]=expected;
            
            var actual=Object.Clone(target)[expected];
            
            Assert.Equal(expected,actual);
        }        
        
        [Fact]
        function ReturnsObjectIfPassedObject(){
            var expected=new Object();
            
            var actual=Object.Clone(expected);
            
            Assert.True(Object.IsType(Object,expected));
        }

        [Fact]
        function ReturnsNewObjectIfPassedObject(){
            var expected=new Object();
            
            var actual=Object.Clone(expected);
            
            Assert.NotSame(Object.IsType(Object,expected));
        }
        
        [Fact]
        function CopiesExpandoPropertyOntoNewObject(){
            var expected="expected";
            var target=new Object();
            target[expected]=expected;
            
            var actual=Object.Clone(target)[expected];
            
            Assert.Equal(expected,actual);
        }
        
        [Fixture]
        function CopiesGlitchedPropertiesOntoNewObject(){
            [Fact]
            function CopiesConstructor(){
                var expected=Boolean;
                var target={};
                var targetProperty="constructor";
                target[targetProperty]=expected;
            
                var actual=Object.Clone(target)[targetProperty];
                
                Assert.Equal(expected,actual);
            }

            [Fact]
            function CopiesToString(){
                var expected=function(){};
                var target={};
                var targetProperty="toString";
                target[targetProperty]=expected;
            
                var actual=Object.Clone(target)[targetProperty];
                
                Assert.Equal(expected,actual);
            }

            [Fact]
            function CopiesValueOf(){
                var expected=function(){};
                var target={};
                var targetProperty="valueOf";
                target[targetProperty]=expected;
            
                var actual=Object.Clone(target)[targetProperty];
                
                Assert.Equal(expected,actual);
            }

            [Fact]
            function CopiestoLocaleString(){
                var expected=function(){};
                var target={};
                var targetProperty="toLocaleString";
                target[targetProperty]=expected;
            
                var actual=Object.Clone(target)[targetProperty];
                
                Assert.Equal(expected,actual);
            }

            [Fact]
            function CopiesPrototype(){
                var expected={expected:"expected"};
                var target={};
                var targetProperty="prototype";
                target[targetProperty]=expected;
            
                var actual=Object.Clone(target)[targetProperty];
                
                Assert.Equal(expected,actual);
            }

            [Fact]
            function CopiesIsPrototypeOf(){
                var expected=function(){};
                var target={};
                var targetProperty="isPrototypeOf";
                target[targetProperty]=expected;
            
                var actual=Object.Clone(target)[targetProperty];
                
                Assert.Equal(expected,actual);
            }

            [Fact]
            function CopiesPropertyIsEnumerable(){
                var expected=function(){};
                var target={};
                var targetProperty="propertyIsEnumerable";
                target[targetProperty]=expected;
            
                var actual=Object.Clone(target)[targetProperty];
                
                Assert.Equal(expected,actual);
            }

            [Fact]
            function CopiesHasOwnProperty(){
                var expected=function(){};
                var target={};
                var targetProperty="hasOwnProperty";
                target[targetProperty]=expected;
            
                var actual=Object.Clone(target)[targetProperty];
                
                Assert.Equal(expected,actual);
            }
            
            [Fact]
            function CopiesLength(){
                var expected=1;
                var target={};
                var targetProperty="length";
                target[targetProperty]=expected;
            
                var actual=Object.Clone(target)[targetProperty];
                
                Assert.Equal(expected,actual);
            }

            [Fact]
            function CopiesUnique(){
                var expected=function(){};
                var target={};
                var targetProperty="unique";
                target[targetProperty]=expected;
            
                var actual=Object.Clone(target)[targetProperty];
                
                Assert.Equal(expected,actual);
            }
        }
    }
    
    [Fixture]
    function Contains(){
        [Fact]
        function ThrowsIfExpectedIsOmitted(){
            var expected="Object.Contains: 'expected' must be a valid Object.";
            
            var actual=Record.Exception(function(){
                Object.Contains();
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfExpectedIsUndefined(){
            var expected="Object.Contains: 'expected' must be a valid Object.";
            
            var actual=Record.Exception(function(){
                Object.Contains(undefined);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfExpectedIsNull(){
            var expected="Object.Contains: 'expected' must be a valid Object.";
 
            var actual=Record.Exception(function(){
                Object.Contains(null);
            });

            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ReturnsFalseIfActualIsOmitted(){
            var actual=Object.Contains(new Object());        

            Assert.False(actual);
        }

        [Fact]
        function ReturnsFalseIfActualIsUndefined(){
            var actual=Object.Contains(new Object(),undefined);

            Assert.False(actual);
        }

        [Fact]
        function ReturnsFalseIfActualIsNull(){
            var actual=Object.Contains(new Object(),null);

            Assert.False(actual);
        }
        
        [Fact]
        function CallsArrayContainsIfActualIsAnArray(){
            var targetContains=Array.Contains;
            Array.Contains=function(){
                actual=true;
            }
            var actual=false;

            Object.Contains(new Object(),new Array());
            Array.Contains=targetContains;
            
            Assert.True(actual);
        }

        [Fact]
        function CallsStringContainsIfActualIsAString(){
            var targetContains=String.Contains;
            String.Contains=function(){
                actual=true;
            }
            var actual=false;
            
            Object.Contains(new Object(),new String());
            String.Contains=targetContains;
            
            Assert.True(actual);
        }

        [Fact]
        function ReturnsTrueIfExpectedIsEmptyObject(){
            var actual=Object.Contains({},{});
        
            Assert.True(actual);
        }
        
        [Fact]
        function CallsObjectEqualsToCheckSimpleProperty(){
            var targetEquals=Object.Equals;
            Object.Equals=function(){
                actual=true;
            }
            var actual=false;

            Object.Contains({target:"target"},{target:"target"});
            Object.Equals=targetEquals;
            
            Assert.True(actual);
        }
        
        [Fact]
        function CallsPredicateToCheckComplexProperty(){
            var target={
                target:function(){
                    actual=true;
                }
            }
            var actual=false;
            
            Object.Contains(target,{target:""});
            
            Assert.True(actual);
        }

        [Fact]
        function PassesPropertyToExpectedPredicate(){
            var target={
                target:function(targetActual){
                    actual=targetActual;
                }
            }
            var expected="expected";
            var actual=null;
            
            Object.Contains(target,{target:expected});
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function PassesContextToExpectedPredicate(){
            var target={
                target:function(targetActual,targetContext){
                    actual=targetContext;
                }
            }
            var targetInstance={target:"expected"};
            var expected={
                Cancel:false,
                Current:"target",
                Instance:targetInstance,
                Matches:target
            };
            var actual=null;
            
            Object.Contains(target,targetInstance);
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function StopsProcessingIfCancelIsSetOnContext(){
            var target={
                propertyOne:function(targetActual,targetContext){
                    targetContext.Cancel=true;
                },
                propertyTwo:function(){
                    throw new Error("Did not stop processing.");
                }
            };
            
            var actual=Record.Exception(function(){
                Object.Contains(target,{});
            });
        
            Assert.Null(actual);
        }

        [Fact]
        function ProcessesMultiplePropertiesIfCancelIsNotSetOnContext(){
            var target={
                propertyOne:function(targetActual,targetContext){
                    actual++;
                    return true;
                },
                propertyTwo:function(){
                    actual++;
                }
            };
            var expected=2;
            var actual=0;
            
            Object.Contains(target,{});
        
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ReturnsFalseIfPropertyDelegateReturnsFalse(){
            var target={
                propertyOne:function(targetActual,targetContext){
                    return false;
                }
            };
            
            var actual=Object.Contains(target,{});
        
            Assert.False(actual);
        }

        [Fact]
        function ReturnsFalseIfAnyPropertyDelegateReturnsFalse(){
            var target={
                propertyOne:function(targetActual,targetContext){
                    return true;
                },
                propertyTwo:function(targetActual,targetContext){
                    return false;
                },
                propertyThree:function(targetActual,targetContext){
                    return true;
                }
            };
            
            var actual=Object.Contains(target,{});
        
            Assert.False(actual);
        }

        [Fact]
        function ReturnsTrueIfPropertyDelegateReturnsTrue(){
            var target={
                propertyOne:function(targetActual,targetContext){
                    return true;
                }
            };
            
            var actual=Object.Contains(target,{});
        
            Assert.True(actual);
        }

        [Fact]
        function ReturnsTrueIfAllPropertyDelegatesReturnTrue(){
            var target={
                propertyOne:function(targetActual,targetContext){
                    return true;
                },
                propertyTwo:function(targetActual,targetContext){
                    return true;
                },
                propertyThree:function(targetActual,targetContext){
                    return true;
                }
            };
            
            var actual=Object.Contains(target,{});
        
            Assert.True(actual);
        }
        
        [Fact]
        function ReturnsTrueIfMatchingPropertyIsFound(){
            var expected="expected";
            var actual=Object.Contains({target:expected},{target:expected});
        
            Assert.True(actual);
        }

        [Fact]
        function ReturnsFalseIfNoMatchingPropertyIsFound(){
            var actual=Object.Contains({target:"expected"},{target:"actual"});
        
            Assert.False(actual);
        }        
    }
    
    [Fixture]
    function Copy(){
        [Fact]
        function CopiesExpandoFromTargetToSource(){
            var actual={};

            Object.Copy(actual,{value:"expected"});
            
            Assert.NotNull(actual.value);
        }
        
        [Fact]
        function CopiesExpandoValueFromTargetToSource(){
            var expected={value:"expected"};
            var actual={};

            Object.Copy(actual,expected);
            
            Assert.Equal(expected.value,actual.value);
        }
        
        [Fact]
        function MakesOnlyShallowCopiesOfReferences(){
            var expected={value:{value:"expected"}};
            var actual={};

            Object.Copy(actual,expected);

            Assert.Same(expected.value,actual.value);
        }
    }
    
    [Fixture]
    function Equals(){
        [Fact]
        function ThrowsIfExpectedIsNotPassedIn(){
            var expected="Object.Equals: 'expected' must be a valid reference.";

            var actual=Record.Exception(function(){
                Object.Equals();
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfActualIsNotPassedIn(){
            var expected="Object.Equals: 'actual' must be a valid reference.";

            var actual=Record.Exception(function(){
                Object.Equals(expected);
            });

            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ReturnsFalseIfExpectedIsUndefinedAndActualIsNot(){
            var actual=Object.Equals(undefined,{});
        
            Assert.False(actual);
        }
        
        [Fact]
        function SetsReasonIfExpectedIsUndefinedAndActualIsNot(){
            var expected=String.Format("Object.Equals: Expected '{0}', found '{1}'.",String(undefined),{});
            var reason={};
            
            Object.Equals(undefined,{},reason);
            var actual=reason.Value;
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ReturnsTrueIfExpectedAndActualAreBothUndefined(){
            var actual=Object.Equals(undefined,undefined);
            
            Assert.True(actual);
        }
        
        [Fact]
        function CallsArrayEqualsIfPassedAnArrayForExpected(){
            var actual=false;
            var targetEquals=Array.Equals;
            Array.Equals=function(){actual=true;}
        
            Object.Equals(new Array(),null);
            Array.Equals=targetEquals;
            
            Assert.True(actual);
        }

        [Fact]
        function CallsBooleanEqualsIfPassedABooleanForExpected(){
            var actual=false;
            var targetEquals=Boolean.Equals;
            Boolean.Equals=function(){actual=true;}
        
            Object.Equals(new Boolean(),null);
            Boolean.Equals=targetEquals;
            
            Assert.True(actual);
        }

        [Fact]
        function CallsErrorEqualsIfPassedAnErrorForExpected(){
            var actual=false;
            var targetEquals=Error.Equals;
            Error.Equals=function(){actual=true;}
        
            Object.Equals(new Error(),null);
            Error.Equals=targetEquals;
            
            Assert.True(actual);
        }
        
        [Fact]
        function CallsFunctionEqualsIfPassedAFunctionForExpected(){
            var actual=false;
            var targetEquals=Function.Equals;
            Function.Equals=function(){actual=true;}
        
            Object.Equals(new Function(),null);
            Function.Equals=targetEquals;
            
            Assert.True(actual);
        }
        
        [Fact]
        function CallsNumberEqualsIfPassedANumberForExpected(){
            var actual=false;
            var targetEquals=Number.Equals;
            Number.Equals=function(){actual=true;}
        
            Object.Equals(new Number(),null);
            Number.Equals=targetEquals;
            
            Assert.True(actual);
        }
        
        [Fact]
        function CallsStringEqualsIfPassedAStringForExpected(){
            var actual=false;
            var targetEquals=String.Equals;
            String.Equals=function(){actual=true;}
        
            Object.Equals(new String(),null);
            String.Equals=targetEquals;
            
            Assert.True(actual);
        }

        [Fact]
        function ReturnsFalseIfExpectedIsOfUnknownType(){
            var target=new Number();
            target.constructor=function(){};

            var actual=Object.Equals(target,null);
            
            Assert.False(actual);
        }

        [Fact]
        function SetsReasonIfExpectedIsOfUnknownType(){
            var target=new function(){};
            var expected=String.Format("Object.Equals: Expected '{0}', found '{1}'.",target,null);
            var reason={};

            Object.Equals(target,null,reason);
            var actual=reason.Value;
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ReturnsFalseIfActualIsNull(){            
            var actual=Object.Equals({},null);
            
            Assert.False(actual);
        }

        [Fact]
        function SetsReasonIfActualIsNull(){
            var expected=String.Format("Object.Equals: Expected '{0}', found '{1}'.",{},null);
            var reason={};
            
            Object.Equals({},null,reason);
            var actual=reason.Value;
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ReturnsFalseIfActualIsUndefined(){
            var actual=Object.Equals({},undefined);
            
            Assert.False(actual);
        }
        
        [Fact]
        function SetsReasonIfActualIsUndefined(){
            var expected=String.Format("Object.Equals: Expected '{0}', found '{1}'.",{},undefined);
            var reason={};
            
            Object.Equals({},undefined,reason);
            var actual=reason.Value;
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ReturnsFalseIfPropertyIsMissingFromActual(){
            var actual=Object.Equals({expected:"expected"},{});
            
            Assert.False(actual);
        }

        [Fact]
        function SetsReasonIfPropertyIsMissingFromActual(){
            var target={expected:"expected"};
            var expected=String.Format("Object.Equals: property '{0}' does not match. Expected value '{1}', found '{2}'.","expected",target.expected,{}.expected);
            var reason={};
            
            Object.Equals(target,{},reason);
            var actual=reason.Value;
            
            Assert.Equal(expected,actual);
        }

        
        [Fact]
        function ReturnsFalseIfPropertiesDontMatch(){
            var actual=Object.Equals({expected:"expected"},{expected:"actual"});
            
            Assert.False(actual);
        }

        [Fact]
        function SetsReasonIfPropertiesDontMatch(){
            var target={expected:"expected"};
            var expected=String.Format("Object.Equals: property '{0}' does not match. Expected value '{1}', found '{2}'.","expected",target.expected,{}.expected);
            var reason={};

            Object.Equals({expected:"expected"},{},reason);
            var actual=reason.Value;
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ReturnsFalseIfAdditionalPropertyIsFoundOnActual(){
            var actual=Object.Equals({},{expected:"expected"});
            
            Assert.False(actual);
        }
        
        [Fact]
        function SetsReasonIfAdditionalPropertyIsFoundOnActual(){
            var target={actual:"actual"};
            var expected=String.Format("Object.Equals: found unexpected property '{0}' on actual, with value '{1}'",target.actual,target.actual);
            var reason={};
        
            Object.Equals({},target,reason);
            var actual=reason.Value;
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ReturnsTrueIfPropertiesMatch(){
            var expectedTarget={expected:"expected"};
            var actualTarget={expected:"expected"};
            
            var actual=Object.Equals(expectedTarget,actualTarget);
            
            Assert.True(actual);
        }
    }
    
    [Fixture]
    function ForEach(){
        [Fact]
        function ThrowsIfObjectIsUndefined(){
            var expected="Object.ForEach: 'object' must be a valid Object.";
            
            var actual=Record.Exception(function(){
                Object.ForEach(undefined);
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfObjectIsNull(){
            var expected="Object.ForEach: 'object' must be a valid Object.";
            
            var actual=Record.Exception(function(){
                Object.ForEach(null);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfHandlerIsNotAValidFunction(){
            var expected="Object.ForEach: argument 'handler' must be a valid Function pointer.";
            
            var actual=Record.Exception(function(){
                Object.ForEach({},null);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function DoesNotThrowIfPredicateIsOmitted(){
            var actual=Record.Exception(function(){
                Object.ForEach({},function(){});
            });
            
            Assert.Null(actual);
        }

        [Fact]
        function DoesNotThrowIfPredicateIsNull(){
            var actual=Record.Exception(function(){
                Object.ForEach({},function(){},null);
            });
            
            Assert.Null(actual);
        }
        
        [Fact]
        function ThrowsIfPredicateIsNotAValidFunction(){
            var expected="Object.ForEach: 'predicate' must be a valid Function pointer.";
            
            var actual=Record.Exception(function(){
                Object.ForEach({},function(){},{});
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function IgnoresPrototypeMembers(){
            var targetProtoType=Object.prototype;
            Object.prototype={expected:"expected"};
            var target={};
            
            var actual=Record.Exception(function(){
                Object.ForEach(target,function(){
                    throw new Error("ObjectTest.ForEach.IgnoresPrototypeMembers: did not ignore prototype member.");
                });
            });
            Object.prototype=targetProtoType;
            
            Assert.Null(actual);
        }

        [Fact]
        function CallsPredicate(){
            var actual=false;
            
            Object.ForEach({expected:"expected"},function(){},function(){
                actual=true;
            });
            
            Assert.True(actual);
        }
        
        [Fact]
        function PassesPropertyToPredicate(){
            var expected="expected";
            var actual=null;

            Object.ForEach({expected:expected},function(){},function(item){
                actual=item;
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function PassesContextToPredicate(){
            var target={value:"expected"};
            var expected={Cancel:false,Current:target.value,Instance:target,Name:'value'};
            var actual=null;

            Object.ForEach(target,function(){},function(item,context){
                actual=context;
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function DoesNotProcessPropertyWhenPredicateReturnsFalse(){
            var target={value:"expected"};
            var expected={Cancel:false,Current:target.value,Instance:target,Name:'value'};
            var actual=false;

            Object.ForEach(target,function(){
                actual=true;
            },function(){
                return false;
            });

            Assert.False(actual);
        }

        [Fact]
        function DoesNotProcessPropertyWhenPredicateReturnsTrue(){
            var target={value:"expected"};
            var expected={Cancel:false,Current:target.value,Instance:target,Name:'value'};
            var actual=false;

            Object.ForEach(target,function(){
                actual=true;
            },function(){
                return true;
            });

            Assert.True(actual);
        }

        [Fact]
        function CallsHandler(){
            var actual=false;
            
            Object.ForEach({expected:"expected"},function(){
                actual=true;
            });
            
            Assert.True(actual);
        }
        
        [Fact]
        function PassesPropertyToHandler(){
            var expected="expected";
            var actual=null;

            Object.ForEach({expected:expected},function(item){
                actual=item;
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function PassesContextToHandler(){
            var target={value:"expected"};
            var expected={Cancel:false,Current:target.value,Instance:target,Name:'value'};
            var actual=null;

            Object.ForEach(target,function(item,context){
                actual=context;
            });

            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function SettingCancelOnContextStopsProcessing(){
            var target={expected:"expected",error:"error"};
            var expected=1;
            var actual=0;
        
            Object.ForEach(target,function(item,context){
                actual++;
                context.Cancel=true;
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ProcessesAllPropertiesOnObject(){
            var target={value1:"value1",value2:"value2",value3:"value3"};
            var expected=3;
            var actual=0;
            
            Object.ForEach(target,function(){
                actual++;
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ReturnsContextObject(){
            var target={value:"expected"};
            var expected={Cancel:false,Current:target.value,Instance:target,Name:'value'};

            var actual=Object.ForEach(target,function(){});

            Assert.Equal(expected,actual);
        }
    }
    
    [Fixture]
    function Global(){
        [Fact]
        function ReturnsAnObject(){
            var actual=Object.Global();
            
            Assert.NotNull(actual);
        }

        [Fact]
        function ReturnsTheGlobalObject(){
            var expected=Test.Object.GetDecoration().GetAttributes()[2]; // Global Object set as Attribute on Test.Object Fixture
            
            var actual=Object.Global();
            
            Assert.Same(expected,actual);
        }
    }

    [Fixture]
    function GetKeys(){
        [Fact]
        function ThrowsIfTargetIsNull(){
            var expected="Object.GetKeys: 'target' must be a valid Object.";
        
            var actual=Record.Exception(function(){
                Object.GetKeys(null);
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTargetIsUndefined(){
            var expected="Object.GetKeys: 'target' must be a valid Object.";
        
            var actual=Record.Exception(function(){
                Object.GetKeys(undefined);
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTargetIsAnArray(){
            var expected="Object.GetKeys: 'target' must be a valid Object.";
        
            var actual=Record.Exception(function(){
                Object.GetKeys([]);
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTargetIsABoolean(){
            var expected="Object.GetKeys: 'target' must be a valid Object.";
        
            var actual=Record.Exception(function(){
                Object.GetKeys(true);
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTargetIsAnError(){
            var expected="Object.GetKeys: 'target' must be a valid Object.";
        
            var actual=Record.Exception(function(){
                Object.GetKeys(new Error());
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTargetIsAFunction(){
            var expected="Object.GetKeys: 'target' must be a valid Object.";
        
            var actual=Record.Exception(function(){
                Object.GetKeys(function(){});
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTargetIsANumber(){
            var expected="Object.GetKeys: 'target' must be a valid Object.";
        
            var actual=Record.Exception(function(){
                Object.GetKeys(7357);
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTargetIsAString(){
            var expected="Object.GetKeys: 'target' must be a valid Object.";
        
            var actual=Record.Exception(function(){
                Object.GetKeys("target");
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function CallsObjectKeysIfPresent(){        
            var expected="expected";
            var actual=null;
            var mockKeys=Mocks.GetMock(Object,"keys",function(){
                return expected;
            });

            mockKeys(function(){
                actual=Object.GetKeys({});
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function ReturnsArrayOfKeys(){        
            var expected=["expected1","expected2","expected3"];
            var actual=null;
            var mockKeys=Mocks.GetMock(Object,"keys",null);

            mockKeys(function(){
                actual=Object.GetKeys({expected1:7357,expected2:"test",expected3:function (){}});
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function DoesNotReturnKeysFromPrototype(){        
            var actual=null;
            var targetClass=function(){};
            targetClass.prototype.unexpected="unexpected";
            var target=new targetClass();
            var mockKeys=Mocks.GetMock(Object,"keys",null);

            mockKeys(function(){
                actual=Object.GetKeys(target);
            });

            Assert.Empty(actual);
        }
    
    }
    
    [Fixture]
    function GetPredicate(){
        [Fact]
        function ThrowsIfExpectedIsOmitted(){
            var expected="Object.GetPredicate: 'expected' was undefined.";
   
            var actual=Record.Exception(function(){
                Object.GetPredicate();
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfExpectedIsUndefined(){
            var expected="Object.GetPredicate: 'expected' was undefined.";
   
            var actual=Record.Exception(function(){
                Object.GetPredicate(undefined);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfExpectedIsNull(){
            var expected="Object.GetPredicate: 'expected' was undefined.";
   
            var actual=Record.Exception(function(){
                Object.GetPredicate(null);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ReturnsFunction(){
            var actual=Object.GetPredicate(Number);
            
            Assert.True(Object.IsType(Function,actual));
        }

        [Fact]
        function PredicateUsesObjectTypeCheck(){
            var targetObjectType=Object.IsType;
            Object.IsType=function(){
                actual=true;
            }
            var actual=false;
            
            Object.GetPredicate(Number)();
            Object.IsType=targetObjectType;
            
            Assert.True(actual);
        }


        [Fact]
        function PredicateReturnsFalseIfExpectedDoesNotMatchActual(){
            var target=new Number();
            
            var actual=Object.GetPredicate(Boolean)(target);
        
            Assert.False(actual);
        }
        
        [Fact]
        function PredicateReturnsTrueIfExpectedMatchesActual(){
            var target=new Number();
            
            var actual=Object.GetPredicate(Number)(target);
        
            Assert.True(actual);
        }

        [Fact]
        function PredicateReturnsFalseIfExpectedIsNotCustomConstructorOfActual(){
            var target=function(){};
            
            var actual=Object.GetPredicate(target)({});
        
            Assert.False(actual);
        }
        
        [Fact]
        function PredicateReturnsTrueIfExpectedIsCustomConstructorOfActual(){
            var target=function(){};
            
            var actual=Object.GetPredicate(target)(new target());
        
            Assert.True(actual);
        }
    }
    
    [Fixture]
    function GetType(){
        [Fact]
        function ReturnsNullForNull(){
            var actual=Object.GetType(null);
            
            Assert.Null(actual);
        } 
        
        [Fact]
        function ReturnsUndefinedForUndefined(){
            var actual=Object.GetType(undefined);
            
            Assert.Undefined(actual);
        }
        
        [Fact]
        function ReturnsArrayForArray(){
            var expected=Array;
            
            var actual=Object.GetType(new expected());
        
            Assert.Equal(expected,actual);
        }        
        
        [Fact]
        function ReturnsBooleanForBoolean(){
            var expected=Boolean;
            
            var actual=Object.GetType(new expected());
        
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ReturnsErrorForError(){
            var expected=Boolean;
            
            var actual=Object.GetType(new expected());
        
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ReturnsFunctionForFunction(){
            var expected=Function;
            
            var actual=Object.GetType(new expected());
        
            Assert.Equal(expected,actual);
        }        

        [Fact]
        function ReturnsNumberForNumber(){
            var expected=Number;
            
            var actual=Object.GetType(new expected());
        
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ReturnsObjectForObject(){
            var expected=Object;
            
            var actual=Object.GetType(new expected());
        
            Assert.Equal(expected,actual);
        }        
        
        [Fact]
        function ReturnsConstructorForCustomObject(){
            var expected=function(){};
            
            var actual=Object.GetType(new expected());
        
            Assert.Equal(expected,actual);
        }        

        [Fact]
        function ReturnsStringForString(){
            var expected=String;
            
            var actual=Object.GetType(new expected());
        
            Assert.Equal(expected,actual);
        }        
    }
    
    [Fixture]
    function Inherits(){
        [Fact]
        function ThrowsIfTypeIsOmitted(){
            var expected="Object.Inherits: 'type' must be a valid Function pointer.";
            
            var actual=Record.Exception(function(){
                Object.Inherits();
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTypeIsUndefined(){
            var expected="Object.Inherits: 'type' must be a valid Function pointer.";
            
            var actual=Record.Exception(function(){
                Object.Inherits(undefined);
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTypeIsNull(){
            var expected="Object.Inherits: 'type' must be a valid Function pointer.";
            
            var actual=Record.Exception(function(){
                Object.Inherits(null);
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTypeIsNotAValidFunctionPointer(){
            var expected="Object.Inherits: 'type' must be a valid Function pointer.";
            
            var actual=Record.Exception(function(){
                Object.Inherits(new Object());
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function DoesNotThrowIfTypeIsAValidFunctionPointer(){
            var actual=Record.Exception(function(){
                Object.Inherits(function(){});
            });
            
            Assert.Null(actual);
        }
        
        [Fact]
        function ReturnsFalseIfInstanceIsOmitted(){
            var actual=Object.Inherits(function(){});
        
            Assert.False(actual);
        }

        [Fact]
        function ReturnsFalseIfInstanceIsUndefined(){
            var actual=Object.Inherits(function(){},undefined);
        
            Assert.False(actual);
        }
        
        [Fact]
        function ReturnsFalseIfInstanceIsNull(){
            var actual=Object.Inherits(function(){},null);
        
            Assert.False(actual);
        }
        
        [Fact]
        function ReturnsFalseIfConstructorIsUndefined(){
            var target=new Object();
            target.constructor=undefined;
            
            var actual=Object.Inherits(function(){},target);
        
            Assert.False(actual);
        }

        [Fact]
        function ReturnsFalseIfConstructorIsNull(){
            var target=new Object();
            target.constructor=null;
            
            var actual=Object.Inherits(function(){},target);
        
            Assert.False(actual);
        }
        
        [Fact]
        function ReturnsFalseIfConstructorIsConstructor(){
            var target=new Object();
            target.constructor=target;
            
            var actual=Object.Inherits(function(){},target);
        
            Assert.False(actual);
        }

        [Fact]
        function ReturnsTrueIfConstructorIsType(){
            var expected=function(){};
            var target=new Object();
            target.constructor=expected;
            
            var actual=Object.Inherits(expected,target);
        
            Assert.True(actual);
        }
        
        [Fact]
        function CallsObjectIsType(){
            var targetIsType=Object.IsType;
            var targetCalls=0;
            Object.IsType=function(){
                if(++targetCalls==2)actual=true;
                return true;
            }
            var actual=false;

            Object.Inherits(function(){},new Object());
            Object.IsType=targetIsType;
        
            Assert.True(actual);
        }
        
        [Fact]
        function PassesTypeToObjectIsType(){
            var targetIsType=Object.IsType;
            var targetCalls=0;
            Object.IsType=function(type){
                if(++targetCalls==3)actual=type;
                return true;
            }
            var expected=function(){}
            var actual=null;
            var target=new Object();
            target.constructor=new Object();
            
            Object.Inherits(expected,target);
            Object.IsType=targetIsType;
        
            Assert.Equal(expected,actual);        
        }

        [Fact]
        function PassesInstanceConstructorToObjectIsType(){
            var targetIsType=Object.IsType;
            var targetCalls=0;
            Object.IsType=function(type,instance){
                if(++targetCalls==3)actual=instance;
                return true;
            }
            var target=new Object();
            var expected=new Object();
            target.constructor=expected;
            var actual=null;

            Object.Inherits(function(){},target);
            Object.IsType=targetIsType;
        
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function PassesInstanceBaseToObjectIsType(){
            var targetIsType=Object.IsType;
            var targetCalls=0;
            Object.IsType=function(type,instance){
                if(++targetCalls==2)actual=instance;
                return true;
            }
            var expected=function(){};
            var target=function(){};
            target.base=expected;
            var actual=null;
            
            Object.Inherits(function(){},target);
            Object.IsType=targetIsType;
        
            Assert.Equal(expected,actual);        
        }
        
        [Fact]
        function ReturnsWhatObjectTypeReturns(){
            var targetIsType=Object.IsType;
            Object.IsType=function(type,instance){
                return instance;
            }
            var expected="expected";
            var target=new Object();
            target.constructor=expected;
            
            var actual=Object.Inherits(function(){},target);
            Object.IsType=targetIsType;
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ReturnsTrueIfObjectInheritsTarget(){
            var targetBase=function(){};
            var target=function(){};
            target.Inherit(targetBase);
            
            var actual=Object.Inherits(targetBase,new target());
            
            Assert.True(actual);
        }

        [Fact]
        function ReturnsTrueIfObjectInheritsParentTarget(){
            var targetBase=function(){};
            var targetParent=function(){
                this.base();
            };
            targetParent.Inherit(targetBase);
            var target=function(){
                this.base();
            };
            target.Inherit(targetParent);

            var actual=Object.Inherits(targetBase,new target());
            
            Assert.True(actual);
        }

        [Fact]
        function ReturnsTrueIfObjectInheritsParentsParentTarget(){
            var targetBase=function(){};
            var targetParentParent=function(){};
            targetParentParent.Inherit(targetBase);
            var targetParent=function(){};
            targetParent.Inherit(targetParentParent);
            var target=function(){};
            target.Inherit(targetParent);
            
            var actual=Object.Inherits(targetBase,new target());
            
            Assert.True(actual);
        }
    }
    
    [Fixture]
    function Implements(){
        [Fact]
        function ThrowsIfTypeIsUndefined(){
            var expected="Object.Implements: 'type' must be a valid Function pointer.";
            
            var actual=Record.Exception(function(){
                Object.Implements(undefined);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ReturnsFalseIfInstanceIsUndefined(){
            var actual=Object.Implements(Number,undefined);
            
            Assert.False(actual);
        }

        [Fact]
        function ReturnsFalseIfInstanceIsNull(){
            var actual=Object.Implements(Number,null);
            
            Assert.False(actual);
        }
        
        [Fact]
        function InstantiatesInstanceIfTargetIsAFunctionType(){
            var target=function(){
                actual=true;
            }
            var actual=false;
            
            var actual=Object.Implements({},target);
            
            Assert.True(actual);
        }

        [Fact]
        function UsesTargetAsInstanceIfInstantiationThrows(){
            var target=function(){
                throw new Error();
            }
            target.Expected=function(){};
            
            var actual=Object.Implements({Expected:function(){}},target);
            
            Assert.True(actual);
        }
        
        [Fact]
        function ReturnsFalseIfMemberMethodIsNotFound(){
            var target=new function(){
                this.Expected=function(){};
            }
            
            var actual=Object.Implements(target,{});
            
            Assert.False(actual);
        }

        [Fact]
        function ReturnsFalseIfMemberMethodSignatureDoesNotMatch(){
            var target=new function(){
                this.Expected=function(a,b,c){};
            }
            
            var actual=Object.Implements(target,{Expected:function(){}});
            
            Assert.False(actual);
        }

        [Fact]
        function ReturnsFalseIfMemberObjectIsNotFound(){
            var target=new function(){
                this.Expected={};
            }
            
            var actual=Object.Implements(target,{});
            
            Assert.False(actual);
        }
        
        [Fact]
        function ReturnsTrueIfMemberMethodsMatch(){
            var target=new function(){
                this.Expected=function(){};
            }
            
            var actual=Object.Implements(target,{Expected:function(){}});
            
            Assert.True(actual);
        }

        [Fact]
        function ReturnsTrueIfMemberMethodSignaturesMatch(){
            var target=new function(){
                this.Expected=function(a,b,c){};
            }
            
            var actual=Object.Implements(target,{Expected:function(a,b,c){}});
            
            Assert.True(actual);
        }
        
        [Fact]
        function ReturnsTrueIfMemberObjectsFound(){
            var target=new function(){
                this.Expected={};
            }
            
            var actual=Object.Implements(target,{Expected:{}});
            
            Assert.True(actual);
        }
    }

    [Fixture]
    function IsEmpty(){
        [Fact]
        function ThrowsIfInstanceIsUndefined(){
            var expected="Object.IsEmpty: 'instance' was undefined.";

            var actual=Record.Exception(function(){
                Object.IsEmpty();
            });

            Assert.Equal(expected,actual);
        }

        [Fact]
        function CallsArrayIsEmptyForArrays(){
            var expected="expected";
            var targetIsEmpty=Array.IsEmpty;
            Array.IsEmpty=function(){
                return expected;
            }

            var actual=Object.IsEmpty([]);
            Array.IsEmpty=targetIsEmpty;

            Assert.Equal(expected,actual);
        }

        [Fact]
        function ReturnsFalseForBooleanFalse(){
            var actual=Object.IsEmpty(false);

            Assert.False(actual);
        }

        [Fact]
        function ReturnsFalseForBooleanTrue(){
            var actual=Object.IsEmpty(true);

            Assert.False(actual);
        }

        [Fact]
        function ReturnsFalseForDates(){
            var actual=Object.IsEmpty(new Date());

            Assert.False(actual);
        }

        [Fact]
        function CallsErrorIsEmptyForErrors(){
            var expected="expected";
            var targetIsEmpty=Error.IsEmpty;
            Error.IsEmpty=function(){
                return expected;
            }

            var actual=Object.IsEmpty(new Error());
            Error.IsEmpty=targetIsEmpty;

            Assert.Equal(expected,actual);
        }

        [Fact]
        function CallsFunctionIsEmptyForFunctions(){
            var expected="expected";
            var targetIsEmpty=Function.IsEmpty;
            Function.IsEmpty=function(){
                return expected;
            }

            var actual=Object.IsEmpty(new Function());
            Function.IsEmpty=targetIsEmpty;

            Assert.Equal(expected,actual);
        }

        [Fact]
        function ReturnsFalseForNumbers(){
            var actual=Object.IsEmpty(0);

            Assert.False(actual);
        }

        [Fact]
        function CallsStringIsEmptyForStrings(){
            var expected="expected";
            var targetIsEmpty=String.IsEmpty;
            String.IsEmpty=function(){
                return expected;
            }

            var actual=Object.IsEmpty("");
            String.IsEmpty=targetIsEmpty;

            Assert.Equal(expected,actual);
        }

        [Fact]
        function ReturnsFalseForObjectWithProperty(){
            var actual=Object.IsEmpty({target:"target"});
        
            Assert.False(actual);
        }

        [Fact]
        function ReturnsTrueForObjectWithNoProperties(){
            var actual=Object.IsEmpty({});
        
            Assert.True(actual);
        }

    }
    
    [Fixture]
    function IsType(){
        [Fact]
        function ThrowsIfTypeIsUndefined(){
            var expected="Object.IsType: 'type' must be a valid Function pointer.";
            
            var actual=Record.Exception(function(){
                Object.IsType(undefined);
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfTypeIsNull(){
            var expected="Object.IsType: 'type' must be a valid Function pointer.";
            
            var actual=Record.Exception(function(){
                Object.IsType(null);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ReturnsFalseIfInstanceIsUndefined(){
            var actual=Object.IsType(function(){},undefined);
            
            Assert.False(actual);
        }

        [Fact]
        function ReturnsFalseIfInstanceIsNull(){
            var actual=Object.IsType(function(){},null);
            
            Assert.False(actual);
        }
        
        [Fact]
        function ReturnsTrueIfTypeIsErrorAndInstanceConstructorReturnsCustomObjectError(){
            var targetError={};
            targetError.constructor={toString:function(){return "[object Error]"}};

            var actual=Object.IsType(Error,targetError);
        
            Assert.True(actual);
        }

        [Fact]
        function ReturnsTrueIfTypeIsArrayAndInstanceConstructorIsArray(){
            var targetType=Array;
            
            var actual=Object.IsType(targetType,new targetType());
        
            Assert.True(actual);
        }
        
        [Fact]
        function ReturnsTrueIfTypeIsBooleanAndInstanceConstructorIsBoolean(){
            var targetType=Boolean;
            
            var actual=Object.IsType(targetType,new targetType());
        
            Assert.True(actual);
        }        

        [Fact]
        function ReturnsTrueIfTypeIsErrorAndInstanceConstructorIsError(){
            var targetType=Error;

            var actual=Object.IsType(targetType,new targetType());
        
            Assert.True(actual);
        }

        [Fact]
        function ReturnsTrueIfTypeIsFunctionAndInstanceConstructorIsFunction(){
            var targetType=Function;
            
            var actual=Object.IsType(targetType,new targetType());
        
            Assert.True(actual);
        }
        
        [Fact]
        function ReturnsTrueIfTypeIsNumberAndInstanceConstructorIsNumber(){
            var targetType=Number;
            
            var actual=Object.IsType(targetType,new targetType);
        
            Assert.True(actual);
        }
        
        [Fact]
        function ReturnsTrueIfTypeIsObjectAndInstanceConstructorIsObject(){
            var targetType=Object;
            
            var actual=Object.IsType(targetType,new targetType);
        
            Assert.True(actual);
        }
        
        [Fact]
        function ReturnsTrueIfTypeIsCustomObjectAndInstanceConstructorIsCustomObject(){
            var targetType=function(){};
            
            var actual=Object.IsType(targetType,new targetType);
        
            Assert.True(actual);
        }

        [Fact]
        function ReturnsTrueIfTypeIsStringAndInstanceConstructorIsString(){
            var targetType=String;
            
            var actual=Object.IsType(targetType,new targetType);
        
            Assert.True(actual);
        }
        
        [Fact]
        function CallsObjectInheritsIfConstructorDoesntMatch(){
            function targetBase(){};
            function targetType(){};
            targetType.Inherit(function targetTypeBase(){});
            var targetInherits=Object.Inherits;
            Object.Inherits=function(){
                actual=true;
                return true;
            }
            var actual=false;
            
            Object.IsType(targetBase,new targetType());
            Object.Inherits=targetInherits;
            
            Assert.True(actual);
        }
        
        [Fact]
        function ReturnsTrueIfInstanceInheritsCustomType(){
            var targetBase=function(){};
            var targetType=function(){};
            targetType.Inherit(targetBase);
            
            var actual=Object.IsType(targetBase,new targetType());
            
            Assert.True(actual);
        }
        
    }
    
    [Fixture]
    function Resolve(){
        [Fact]
        function ReturnsNullIfPathIsOmitted(){
            var actual=Object.Resolve();
        
            Assert.Null(actual);
        }

        [Fact]
        function ReturnsNullIfPathIsUndefined(){
            var actual=Object.Resolve(undefined);
        
            Assert.Null(actual);
        }

        [Fact]
        function ReturnsNullIfPathIsNull(){
            var actual=Object.Resolve(null);
        
            Assert.Null(actual);
        }
        
        [Fact]
        function ReturnsNullIfPathIsNotConvertibleToString(){
            var target={toString:null};

            var actual=Object.Resolve(target);
        
            Assert.Null(actual);
        }
        
        [Fact]
        function ReturnsNullIfPathDoesNotResolve(){
            var actual=Object.Resolve('Expected',{});
            
            Assert.Undefined(actual);
        }
        
        [Fact]
        function ReturnsObjectIfPathResolvesFromRootContainer(){
            var expected={};
            
            var actual=Object.Resolve('Expected',{Expected:expected});
        
            Assert.NotNull(actual);
        }

        [Fact]
        function ReturnsObjectResolvedFromRootContainer(){
            var expected={};
            
            var actual=Object.Resolve('Expected',{Expected:expected});
        
            Assert.Same(expected,actual);
        }
        
        [Fact]
        function ResolvesObjectsMoreThanOneLayerDeep(){
            var expected={};
            
            var actual=Object.Resolve('Target.Expected',{Target:{Expected:expected}});
        
            Assert.NotNull(actual);
        }

        [Fact]
        function ReturnsObjectResolvedMoreThanOneLayerDeep(){
            var expected={};
            
            var actual=Object.Resolve('Target.Expected',{Target:{Expected:expected}});
        
            Assert.Same(expected,actual);
        }

        [Fact]
        function ReturnsObjectIfPathResolvesFromGlobal(){            
            var actual=Object.Resolve('Assert');
        
            Assert.NotNull(actual);
        }

        [Fact]
        function ReturnsObjectResolvedFromGlobal(){
            var expected=Assert;
            
            var actual=Object.Resolve('Assert');
        
            Assert.Same(expected,actual);
        }
    }
    
    [Fixture]
    function Same(){
        [Fact]
        function ReturnsFalseIfExpectedArrayDoesNotMatchActualArray(){
            var actual=Object.Same([],[]);
            
            Assert.False(actual);
        }

        [Fact]
        function ReturnsTrueIfExpectedArrayMatchesActualArray(){
            var target=[];
            
            var actual=Object.Same(target,target);
            
            Assert.True(actual);
        }

        [Fact]
        function ReturnsFalseIfExpectedBooleanDoesNotMatchActualBoolean(){
            var actual=Object.Same(true,false);
            
            Assert.False(actual);
        }

        [Fact]
        function ReturnsTrueIfExpectedBooleanMatchesActualBoolean(){
            var actual=Object.Same(true,true);
            
            Assert.True(actual);
        }

        [Fact]
        function ReturnsFalseIfExpectedErrorDoesNotMatchActualError(){
            var actual=Object.Same(new Error(),new Error());
            
            Assert.False(actual);
        }

        [Fact]
        function ReturnsTrueIfExpectedErrorMatchesActualError(){
            var target=new Error();
            
            var actual=Object.Same(target,target);
            
            Assert.True(actual);
        }
        
        
        [Fact]
        function ReturnsFalseIfExpectedFunctionDoesNotMatchActualFunction(){
            var actual=Object.Same(function(){},function(){});
            
            Assert.False(actual);
        }

        [Fact]
        function ReturnsTrueIfExpectedFunctionMatchesActualFunction(){
            var target=function(){};
            
            var actual=Object.Same(target,target);
            
            Assert.True(actual);
        }
        
        [Fact]
        function ReturnsFalseIfExpectedNumberDoesNotMatchActualNumber(){
            var actual=Object.Same(1,2);
            
            Assert.False(actual);
        }

        [Fact]
        function ReturnsTrueIfExpectedNumberMatchesActualNumber(){
            var actual=Object.Same(1,1);
            
            Assert.True(actual);
        }
        
        
        [Fact]
        function ReturnsFalseIfExpectedObjectDoesNotMatchActualObject(){
            var actual=Object.Same({},{});
            
            Assert.False(actual);
        }
        
        [Fact]
        function ReturnsTrueIfExpectedObjectMatchesActualObject(){
            var target={};
            
            var actual=Object.Same(target,target);
            
            Assert.True(actual);
        }

        [Fact]
        function ReturnsFalseIfExpectedStringDoesNotMatchActualString(){
            var actual=Object.Same("expected","actual");
            
            Assert.False(actual);
        }

        [Fact]
        function ReturnsTrueIfExpectedStringMatchesActualString(){
            var actual=Object.Same("expected","expected");
            
            Assert.True(actual);
        }
    }
    
    [Fixture]
    function Set(){
        [Fact]
        function DoesNotThrowIfObjectIsOmitted(){
            var actual=Record.Exception(function(){
                Object.Set();
            });
            
            Assert.Null(actual);
        }
        [Fact]
        function DoesNotThrowIfObjectIsUndefined(){
            var actual=Record.Exception(function(){
                Object.Set(undefined);
            });
            
            Assert.Null(actual);
        }
        
        [Fact]
        function DoesNotThrowIfObjectIsNull(){
            var actual=Record.Exception(function(){
                Object.Set(null);
            });
            
            Assert.Null(actual);
        }
        
        [Fact]
        function SetsPropertyIfPropertyIsArray(){
            var expected={value:[]};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.Equal(expected.value,actual.value);
        }
        
        [Fact]
        function SetsShallowReferenceToArrayIfPropertyIsArray(){
            var expected={value:[1,2,3]};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.Same(expected.value,actual.value);
        }
        
        [Fact]
        function SetsMatchingCopyOfArrayIfPropertyIsArray(){
            var expected={value:[1,2,3]};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.Equal(expected.value,actual.value);
        }

        [Fact]
        function SetsShallowReferenceToObjectIfPropertyIsObject(){
            var expected={value:{}};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.Same(expected.value,actual.value);
        }
        
        [Fact]
        function SetsMatchingCopyOfObjectIfPropertyIsObject(){
            var expected={value:{}};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.Equal(expected.value,actual.value);
        }
        
        [Fact]
        function SetsNestedObjectIfPropertyIsObject(){
            var expected={value:{nestedValue:"expected"}};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.True(Object.IsType(String,actual.value.nestedValue));
        }

        [Fact]
        function SetsMatchingCopyOfNestedObjectIfPropertyIsObject(){
            var expected={value:{nestedValue:"expected"}};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.Equal(expected.value.nestedValue,actual.value.nestedValue);
        }
        
        [Fact]
        function SetsPropertyIfPropertyIsNull(){
            var expected={value:null};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.Null(actual.value);
        }

        [Fact]
        function SetsBooleanPropertyIfPropertyIsBoolean(){
            var expected={value:new Boolean()};
            var actual={};

            Object.Set(actual,expected);
            
            Assert.True(Object.IsType(Boolean,actual.value));
        }

        [Fact]
        function SetsMatchingBooleanIfPropertyIsBoolean(){
            var expected={value:new Boolean()};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.Equal(expected.value,actual.value);
        }
        
        [Fact]
        function SetsPropertyIfPropertyIsError(){
            var expected={value:new Error("expected")};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.True(Object.IsType(Error,actual.value));
        }
        
        [Fact]
        function SetsMatchingErrorIfPropertyIsError(){
            var expected={value:new Error("expected")};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.Equal(expected.value,actual.value);
        }
        
        [Fact]
        function SetsPropertyIfPropertyIsFunction(){
            var expected={value:new Function()};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.True(Object.IsType(Function,actual.value));
        }
        
        [Fact]
        function SetsMatchingFunctionIfPropertyIsFunction(){
            var expected={value:new Function()};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.Equal(expected.value,actual.value);
        }

        [Fact]
        function SetsPropertyIfPropertyIsNumber(){
            var expected={value:new Number()};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.True(Object.IsType(Number,actual.value));
        }
        
        [Fact]
        function SetsMatchingNumberIfPropertyIsNumber(){
            var expected={value:new Number()};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.Equal(expected.value,actual.value);
        }
        
        [Fact]
        function SetsPropertyIfPropertyIsObject(){
            var expected={value:new Object()};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.True(Object.IsType(Object,actual.value));
        }
        
        [Fact]
        function SetsMatchingObjectIfPropertyIsObject(){
            var expected={value:new Object()};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.Equal(expected.value,actual.value);
        }
        
        [Fact]
        function SetsPropertyIfPropertyIsString(){
            var expected={value:new String("expected")};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.True(Object.IsType(String,actual.value));
        }
        
        [Fact]
        function SetsMatchingStringIfPropertyIsString(){
            var expected={value:new String("expected")};
            var actual={};
            
            Object.Set(actual,expected);
            
            Assert.Equal(expected.value,actual.value);
        }
    }
}